﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Windows.Controls.Specialized.TextModel;

namespace Microsoft.Windows.Controls.Logic {
    
    public interface IEditorOperations {

        /// <summary>
        /// Moves to the next character.
        /// </summary>
        /// <param name="select">
        /// Specifies whether selection is made as the caret is moved.
        /// </param>
        void MoveToNextCharacter(bool select);

        /// <summary>
        /// Moves to the previous character.
        /// </summary>
        /// <param name="select">
        /// Specifies whether selection is made as the caret is moved.
        /// </param>
        void MoveToPreviousCharacter(bool select);

        /// <summary>
        /// Moves the caret to the next word.
        /// </summary>
        /// <param name="select">
        /// Specifies whether or not selection is extended as the caret is moved.
        /// </param>
        void MoveToNextWord(bool select);

        /// <summary>
        /// Moves the caret to the previous word.
        /// </summary>
        /// <param name="select">
        /// Specifies whether or not selection is extended as the caret is moved.
        /// </param>
        void MoveToPreviousWord(bool select);

        /// <summary>
        /// Puts the caret one line up.
        /// </summary>
        /// <param name="select">
        /// Specifies whether selection is made as the caret is moved.
        /// </param>
        void MoveLineUp(bool select);

        /// <summary>
        /// Puts the caret one line down.
        /// </summary>
        /// <param name="select">
        /// Specifies whether selection is made as the caret is moved.
        /// </param>
        void MoveLineDown(bool select);

        /// <summary>
        /// Moves the caret one page up.
        /// </summary>
        /// <param name="select">
        /// Specifies whether selection is made as the caret is moved.
        /// </param>
        void PageUp(bool select);

        /// <summary>
        /// Moves the caret one page down.
        /// </summary>
        /// <param name="select">
        /// Specifies whether selection is made as the caret is moved.
        /// </param>
        void PageDown(bool select);

        /// <summary>
        /// Moves the caret to the end of the line.
        /// </summary>
        /// <param name="select">
        /// Specifies whether selection is made as the caret is moved.
        /// </param>
        void MoveToEndOfLine(bool select);

        /// <summary>
        /// Moves the caret to the start of the line.
        /// </summary>
        /// <param name="select">
        /// Specifies whether selection is made as the caret is moved.
        /// </param>
        /// <remarks>
        /// <para>1. If in the middle of the line, go to the start of the first non-white space character</para>
        /// <para>2. If at the start of the first white space character, go to the start of the line</para>
        /// <para>3. If at the start of the line containing non white space character, go to the start of the first non-white space character</para>
        /// <para>4. If at the start of the line with only white space, go to the start of the line</para>
        /// </remarks>
        void MoveToStartOfLine(bool select);

        /// <summary>
        /// Sets the caret at the start of the specified line.
        /// </summary>
        /// <param name="lineNumber">
        /// The line number to set the caret at.
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="lineNumber"/> is less than 0 or greater than the line number of the last line in the TextBuffer.</exception>
        void GotoLine(int lineNumber);

        /// <summary>
        /// Sets the caret at the start of the document.
        /// </summary>
        /// <param name="select">
        /// Specifies whether selection is made as the caret is moved.
        /// </param>
        void MoveToStartOfDocument(bool select);

        /// <summary>
        /// Sets the caret at the end of the document.
        /// </summary>
        /// <param name="select">
        /// Specifies whether selection is made as the caret is moved.
        /// </param>
        void MoveToEndOfDocument(bool select);

        /// <summary>
        /// Moves the current line to the top of the view.
        /// </summary>
        void MoveCurrentLineToTop();

        /// <summary>
        /// Moves the current line to the bottom of the view.
        /// </summary>
        void MoveCurrentLineToBottom();

        /// <summary>
        /// Scrolls the view either up by one line,
        /// reposition caret only if it is scrolled off the page. 
        /// It will reposition the cursor to the newly scrolled line
        /// at the bottom of the view.
        /// </summary>
        void ScrollUpAndMoveCaretIfNecessary();

        /// <summary>
        /// Scrolls the view either up by one line,
        /// reposition caret only if it is scrolled off the page. 
        /// It will reposition the cursor to the newly scrolled line
        /// at the top of the view.
        /// </summary>
        void ScrollDownAndMoveCaretIfNecessary();

        /// <summary>
        /// Deletes a character to the left of the current caret.
        /// </summary>
        /// <param name="undoHistory">
        /// UndoHistory to add this operation to.
        /// </param>
        /// <exception cref="ArgumentNullException"><paramref name="undoHistory"/> is null.</exception>
        void DeleteCharacterToLeft(UndoHistory undoHistory);

        /// <summary>
        /// Deletes a character to the right of the current caret.
        /// </summary>
        /// <param name="undoHistory">
        /// UndoHistory to add this operation to.
        /// </param>
        /// <exception cref="ArgumentNullException"><paramref name="undoHistory"/> is null.</exception>
        void DeleteCharacterToRight(UndoHistory undoHistory);

        /// <summary>
        /// Deletes the word to the right of the current caret position.
        /// </summary>
        /// <param name="undoHistory">
        /// UndoHistory to add this operation to.
        /// </param>
        /// <exception cref="ArgumentNullException"><paramref name="undoHistory"/> is null.</exception>
        void DeleteWordToRight(UndoHistory undoHistory);

        /// <summary>
        /// Deletes the word to the left of the current caret position.
        /// </summary>
        /// <param name="undoHistory">
        /// UndoHistory to add this operation to.
        /// </param>
        /// <exception cref="ArgumentNullException"><paramref name="undoHistory"/> is null.</exception>
        void DeleteWordToLeft(UndoHistory undoHistory);

        /// <summary>
        /// Inserts a new line at the current caret position.
        /// </summary>
        /// <param name="undoHistory">
        /// UndoHistory to add this operation to.
        /// </param>
        /// <exception cref="ArgumentNullException"><paramref name="undoHistory"/> is null.</exception>
        void InsertNewline(UndoHistory undoHistory);

        /// <summary>
        /// Inserts a Tab at the current Caret position.
        /// </summary>
        /// <param name="undoHistory">
        /// UndoHistory to add this operation to.
        /// </param>
        /// <exception cref="ArgumentNullException"><paramref name="undoHistory"/> is null.</exception>
        void InsertTab(UndoHistory undoHistory);

        /* Not implemented *
        /// <summary>
        /// Removes a Tab previous to the current Caret position.
        /// </summary>
        /// <param name="undoHistory">
        /// UndoHistory to add this operation to.
        /// </param>
        /// <exception cref="ArgumentNullException"><paramref name="undoHistory"/> is null.</exception>
        void RemovePreviousTab(UndoHistory undoHistory);

        /// <summary>
        /// Inserts a Tab at the beginning of all the lines in the selection.
        /// </summary>
        /// <param name="undoHistory">
        /// UndoHistory to add this operation to.
        /// </param>
        /// <exception cref="InvalidOperationException">There is no selection on the textview.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="undoHistory"/> is null.</exception>
        void IndentSelection(UndoHistory undoHistory);

        /// <summary>
        /// Deletes a Tab from the beginning of all the lines in the selection.
        /// </summary>
        /// <param name="undoHistory">
        /// UndoHistory to add this operation to.
        /// </param>
        /// <exception cref="ArgumentNullException"><paramref name="undoHistory"/> is null.</exception>
        /// <exception cref="InvalidOperationException">There is no selection on the textview.</exception>
        void UnindentSelection(UndoHistory undoHistory);
        */

        /// <summary>
        /// Inserts the given text at the current caret position.
        /// </summary>
        /// <param name="text">
        /// The text to be inserted in the buffer.
        /// </param>
        /// <param name="undoHistory">
        /// UndoHistory to add this operation to.
        /// </param>
        /// <exception cref="ArgumentNullException"><paramref name="text"/> is null.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="undoHistory"/> is null.</exception>
        void InsertText(string text, UndoHistory undoHistory);

        /// <summary>
        /// Inserts the given text at the current caret position as provisional text.
        /// </summary>
        /// <param name="text">
        /// The text to be inserted in the buffer.
        /// </param>
        /// <param name="undoHistory">
        /// UndoHistory to add this operation to.
        /// </param>
        /// <remarks>
        /// Provisional text is automatically replaced by subsequent InsertText() or InsertProvisionalText() calls.
        /// </remarks>
        /// <exception cref="ArgumentNullException"><paramref name="text"/> is null.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="undoHistory"/> is null.</exception>
        void InsertProvisionalText(string text, UndoHistory undoHistory);

        /*
        /// <summary>
        /// The span of the current provisional composition (null if there is no provisional composition).
        /// </summary>
        ITrackingSpan ProvisionalCompositionSpan { get; }
        */

        /// <summary>
        /// Deletes the selected range of text.
        /// </summary>
        /// <param name="undoHistory">UndoHistory to add this operation to.</param>
        /// <returns>
        /// Returns true if a selection was found and deleted, false if a selection was not found.
        /// </returns>
        /// <exception cref="ArgumentNullException"><paramref name="undoHistory"/> is null.</exception>
        bool DeleteSelection(UndoHistory undoHistory);

        /// <summary>
        /// Replace text selection with the new text.
        /// </summary>
        /// <param name="text">
        /// The new text that will replace the old selection.
        /// </param>
        /// <param name="undoHistory">
        /// UndoHistory to add this operation to.
        /// </param>
        /// <exception cref="ArgumentNullException"><paramref name="text"/> is null.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="undoHistory"/> is null.</exception>
        void ReplaceSelection(string text, UndoHistory undoHistory);

        /*
        /// <summary>
        /// Transposes character at the cursor with next character. 
        /// Transpose first two characters when cursor at the start of the line, 
        /// transpose last two characters when cursor at the end of the line.
        /// </summary>
        /// <param name="undoHistory">
        /// UndoHistory to add this operation to.
        /// </param>
        /// <exception cref="ArgumentNullException"><paramref name="undoHistory"/> is null.</exception>
        void TransposeCharacter(UndoHistory undoHistory);

        /// <summary>
        /// Transposes line containing the cursor with the next line. Transpose last two lines when cursor at the last line.
        /// </summary>
        /// <param name="undoHistory">
        /// UndoHistory to add this operation to.
        /// </param>
        /// <exception cref="ArgumentNullException"><paramref name="undoHistory"/> is null.</exception>
        void TransposeLine(UndoHistory undoHistory);

        /// <summary>
        /// Coverts uppercase letters to lowercase in select text or next character to the cursor if select is empty.
        /// </summary>
        /// <param name="undoHistory">
        /// UndoHistory to add this operation to.
        /// </param>
        /// <exception cref="ArgumentNullException"><paramref name="undoHistory"/> is null.</exception>
        void MakeLowercase(UndoHistory undoHistory);

        /// <summary>
        /// Coverts lowercase letters to uppercase in select text or next character to the cursor if select is empty.
        /// </summary>
        /// <param name="undoHistory">
        /// UndoHistory to add this operation to.
        /// </param>
        /// <exception cref="ArgumentNullException"><paramref name="undoHistory"/> is null.</exception>
        void MakeUppercase(UndoHistory undoHistory);

        /// <summary>
        /// Replace text from the given span with the new text.
        /// </summary>
        /// <param name="replaceSpan">The span of text to be replaced.</param>
        /// <param name="text">
        /// The new text that will replace the old selection.
        /// </param>
        /// <param name="undoHistory">
        /// UndoHistory to add this operation to.
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="start"/> is less than 0 or greater than the index of the last character in the TextBuffer.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="length"/> is less than 0.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="undoHistory"/> is null.</exception>
        void ReplaceText(Span replaceSpan, string text, UndoHistory undoHistory);

        /// <summary>
        /// Replaces all matching occurrences of the given string.
        /// </summary>
        /// <param name="searchText">
        /// Text to match.
        /// </param>
        /// <param name="replaceText">
        /// Text used in replace.
        /// </param>
        /// <param name="matchCase">
        /// True if search should match case, false otherwise.
        /// </param>
        /// <param name="matchWholeWord">
        /// True if search should match whole word, false otherwise.
        /// </param>
        /// <param name="useRegularExpressions">
        /// True if search should use regular expression, false otherwise.
        /// </param>
        /// <param name="undoHistory">
        /// UndoHistory to add this operation to.
        /// </param>
        /// <exception cref="ArgumentNullException"><paramref name="searchText"/> is null.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="undoHistory"/> is null.</exception>
        /// <exception cref="ArgumentException"> if <paramref name="useRegularExpressions"/> is true and <paramref name="searchText"/> is an invalid regular expression.</exception>
        int ReplaceAllMatches(string searchText, string replaceText, bool matchCase, bool matchWholeWord, bool useRegularExpressions, UndoHistory undoHistory);
        */

        /// <summary>
        /// Selects the current word.
        /// </summary>
        void SelectCurrentWord();

        /// <summary>
        /// Select the current line
        /// </summary>
        void SelectCurrentLine();

        /*
        /// <summary>
        /// Selects the enclosing.
        /// </summary>
        void SelectEnclosing();

        /// <summary>
        /// Selects the first child.
        /// </summary>
        void SelectFirstChild();

        /// <summary>
        /// Selects the next sibling.
        /// </summary>
        /// <param name="extendSelection">Specifies whether the selection is to be extended or a new selection is to be made.</param>
        void SelectNextSibling(bool extendSelection);

        /// <summary>
        /// Selects the previous sibling.
        /// </summary>
        /// <param name="extendSelection">Specifies whether the selection is to be extended or a new selection is to be made.</param>
        void SelectPreviousSibling(bool extendSelection);

        /// <summary>
        /// Selects the given line.
        /// </summary>
        /// <param name="lineNumber">
        /// The line number to select.
        /// </param>
        /// <param name="extendSelection">
        /// Specifies whether the selection is to be extended or a new selection is to be made.
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="lineNumber"/> is less than 0, or greater than the number of the last line in the TextBuffer.</exception>
        void SelectLine(int lineNumber, bool extendSelection);
        */

        /// <summary>
        /// Selects all text.
        /// </summary>
        void SelectAll();

        /// <summary>
        /// Extends the current selection span to the new selection end.
        /// </summary>
        /// <param name="newEnd">
        /// The new character position to extend the selection to.
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="newEnd"/> is less than 0.</exception>
        void ExtendSelection(int newEnd);

        /*
        /// <summary>
        /// Moves the caret to the given <paramref name="textLine"/> at the given horizontal offset <paramref name="horizontalOffset"/>,
        /// and extends the current selection span to the new caret position.
        /// </summary>
        /// <param name="textLine">The <see cref="IRenderedTextLine"/> on which to place the caret.</param>
        /// <param name="horizontalOffset">The horizontal location in the given <paramref name="textLine"/> at which to move the caret.</param>
        /// <exception cref="ArgumentNullException"><paramref name="textLine"/> is null.</exception>
        void MoveCaretAndExtendSelection(IRenderedTextLine textLine, double horizontalOffset);
        */

        /// <summary>
        /// Resets any selection in the text.
        /// </summary>
        void ResetSelection();

        /*
        /// <summary>
        /// Copies the selected text to clip board.
        /// </summary>
        void CopySelection();

        /// <summary>
        /// Cuts the selected text.
        /// </summary>
        /// <param name="undoHistory">
        /// UndoHistory to add this operation to.
        /// </param>
        /// <exception cref="ArgumentNullException"><paramref name="undoHistory"/> is null.</exception>
        void CutSelection(UndoHistory undoHistory);

        /// <summary>
        /// Pastes text from the clipboard to the text buffer.
        /// </summary>
        /// <param name="undoHistory">
        /// UndoHistory to add this operation to.
        /// </param>
        /// <exception cref="ArgumentNullException"><paramref name="undoHistory"/> is null.</exception>
        void Paste(UndoHistory undoHistory);

        /// <summary>
        /// Gets whether or not a paste operation can happen.
        /// </summary>
        bool CanPaste {
            get;
        }
        
        
        /// <summary>
        /// The text view on which these operations work.
        /// </summary>
        ITextView TextView {
            get;
        }
        

        /// <summary>
        /// Gets or sets whether we are in overwrite mode.
        /// </summary>
        bool OverwriteMode {
            get;
            set;
        }

        IEditorOptions Options {
            get;
        }
 */
    }
}
